import os
import subprocess
import time
#import winshell
import psutil
#import filecmp
from PIL import Image
from PIL import ImageGrab
import pygetwindow as gw
#import SendEmail4TestResult
#import shutil
#import math
#import operator
from functools import reduce
#from git import Repo
#import win32gui
#import win32ui
#import win32con
import SendEmail4TestResult

"""
控制台显示：
1.xxx不是内部或外部命令，也不是可运行的程序或批处理文件 --> CppProject.exe/UI_Simulator.exe启动失败，具体信息可根据前面列出的导致此报错的指令确定
2.错误: 没有找到进程 "xxx" --> 如未与1同时出现，则CppProject.exe提前结束，可能发生崩溃
"""

#以下路径根据本地存储位置自行修改
bin_folder_path = "D:\\Test"
cppproject_exe_path = "E:\\Projects\\Package\\Windows\\CppProjectTest.exe"
uisimulator_exe_path = "E:\\Projects\\UI_Simulator\\x64\\Debug\\UI_Simulator.exe"


#执行cmd命令启动Simulator，并得到执行后的返回值，python调试界面输出返回值（不会弹出cmd控制台）
def run_cmd_Popen_uisimulator(cmd_string):  
    print('运行cmd指令：{}'.format(cmd_string))
    while(get_pid_by_name("UI_Simulator.exe") != -1):#保证同时只有一个进程一个测试在运行
        print("等待上一个测试结束...")
        time.sleep(2)#等待2s
    uisimulator_process = subprocess.Popen(cmd_string,shell=True, stdout=None, stderr=None)
    time.sleep(1)#等待1s启动时间，以免误判
    try:
        uisimulator_process
        if(get_pid_by_name("UI_Simulator.exe") == -1):
            print("\033[31mUI_Simulator启动失败\033[0m")
            return False
        print("\033[32mUI_Simulator启动成功\033[0m")
        return get_pid_by_name("UI_Simulator.exe")
    except subprocess.CalledProcessError as e:
        print('\033[31m{}\033[0m'.format(e))
        return False

#执行cmd命令启动CppProject，并得到执行后的返回值，python调试界面输出返回值（不会弹出cmd控制台）
def run_cmd_Popen_cppproject():  
    print('运行cmd指令：{}'.format(cppproject_exe_path))
    while get_pid_by_name("CppProject.exe") != -1:#保证同时只有一个进程一个测试在运行
        print("等待上一个测试结束...")
        time.sleep(2)#等待2s
    cppproject_process = subprocess.Popen(cppproject_exe_path,shell=True, stdout=None, stderr=None)
    time.sleep(10)#等待10s启动时间，以免误判
    try:
        cppproject_process
        if get_pid_by_name("CppProject.exe") == -1:
            print("\033[31mCppProject启动失败\033[0m")
            return False
        print("\033[32mCppProject启动成功\033[0m")
        return cppproject_process.pid
    except subprocess.CalledProcessError as e:
        print('\033[31m{}\033[0m'.format(e))
        return False

#获取路径path下所有filetype类型的文件的路径（路径下的文件夹内的文件也会被遍历到）
def get_file_path_list(path, filetype): 
    pathList = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith(filetype):
                pathList.append(os.path.join(root, file))
    return pathList

#根据名字获取进程id
def get_pid_by_name(name):
    pid = -1
    ps = psutil.process_iter()
    for p in ps:
        if p.name() == name:
            pid = p.pid
            break
    return pid

#根据id杀死进程
def kill_process_by_pid(pid):
    subprocess.Popen("taskkill /F /T /PID " + str(pid) , shell=True)

def analyze_test_results(list):
    passed_test_num = 0
    failed_test_num = 0
    all_test_num = 0
    failed_test_list = []
    content = ""
    for test_result in list:
        all_test_num+= 1
        if test_result[1] == False:
            failed_test_num+=1
            failed_test_list.append(test_result[0])
            content += "测试"+ test_result[0] + "启动CppProject.exe失败\n"
            print("测试"+ test_result[0] + "\033[31m启动CppProject.exe失败\033[0m")
        else:
            if test_result[2] == False:
                failed_test_num+=1
                failed_test_list.append(test_result[0])
                content += "测试"+ test_result[0] + "启动UI_Simulator.exe失败\n"
                print("测试"+ test_result[0] + "\033[31m启动UI_Simulator.exe失败\033[0m")
            else:
                if test_result[3] == False:
                    failed_test_num+=1
                    failed_test_list.append(test_result[0])
                    content += "测试"+ test_result[0] + "CppProject.exe提前结束\n"
                    print("测试"+ test_result[0] + "\033[31mCppProject.exe提前结束\033[0m")
                else:
                    passed_test_num+=1
                    content += "测试"+ test_result[0] + "成功\n"
                    print("测试"+ test_result[0] + "\033[32m成功\033[0m")
    content += "共计{}个测试".format(all_test_num) + "，通过{}个".format(passed_test_num)
    print('共计\033[32m{}\033[0m个测试'.format(all_test_num) + '，通过\033[32m{}\033[0m个'.format(passed_test_num))
    if failed_test_num > 0:
        content += ",失败{}个".format(failed_test_num) + ",为：\n"
        print('失败\033[31m{}\033[0m个'.format(failed_test_num) + ",为：")
        for failed_test in failed_test_list:
            content += "{}".format(failed_test)
            print('\033[31m{}\033[0m'.format(failed_test))
    print("")
    
    ret = SendEmail4TestResult.mail(content)
    if ret:
        print("邮件发送成功")
    else:
        print("邮件发送失败")

def main():
    pathList = get_file_path_list(bin_folder_path, "bin");
    test_result_list =[]
    for path in pathList:
        test_result = [path]
        print("=====================================测试 " + path + "开始=====================================")
        cppproject_pid = run_cmd_Popen_cppproject()
        test_result.append(cppproject_pid)
        if cppproject_pid != False:
            simulator_pid = run_cmd_Popen_uisimulator(uisimulator_exe_path + ' ' + path)
            test_result.append(simulator_pid)
            while get_pid_by_name("UI_Simulator.exe") != -1:
                if get_pid_by_name("CppProject.exe") == -1:
                    print("\033[31mCppProject已退出\033[0m")
                    test_result.append(False)
                    break
                print("测试中...")
                time.sleep(2)
            test_result.append(True)
            if get_pid_by_name("CppProject.exe") != -1:
                kill_process_by_pid(cppproject_pid)
            if get_pid_by_name("UI_Simulator.exe") != -1:
                kill_process_by_pid(get_pid_by_name("UI_Simulator.exe"))
            time.sleep(1)#给关闭进程和输出关闭结果留时间
        else:
            test_result.extend(False, False)
        print("=====================================测试 " + path + "结束=====================================")
        print("")
        test_result_list.append(test_result)
    analyze_test_results(test_result_list)
    return

if __name__ == "__main__":
    main()
